package Communication;
import idp.MainController;
import debuggen.Debug;
import Command.*;
/**
 * Communication
 * @author Danny
 *
 */
public class Communication implements Runnable {
	// BT Connection
	private Bluetooth btConnection;
	// Are we ready? If so, the connection will be closed
	private boolean isReady = false;
	// ArrayList with commands, which need to be send
	private CommandStack stckCommand = new CommandStack();
	// Connection with main controller
	private MainController mController;
	
	/**
	 * Constructor
	 */
	public Communication(MainController p_mcController) 
	{
		mController = p_mcController;
	}
	/**
	 * start
	 * Start the communication!
	 */
	public void start()
	{
		// Start bt!
		Thread t = new Thread(this);
		t.start();
	}
	/**
	 * Config communication class
	 */
	private void config()
	{
		// Get bt connection
		btConnection = BluetoothConnection.getInstance(); 
		// Check if there is a connection, if not make one
		if(!btConnection.isConnected())
		{
			// Connect
			// This could take some time..!
			btConnection.connect();
		}
		
		// If in debug mode, write info about BT connection to log.
		if(Debug.DEBUGGEN)
		{
			Debug.writeMessage("Communication class BLUETOOTH connected: " + btConnection.isConnected());
		}
	}
	/**
	 * processCommand
	 * Puts the command on the stack
	 * @param p_cmdCommand
	 */
	public synchronized void processCommand(Command p_cmdCommand)
	{
		stckCommand.push(p_cmdCommand);
	}
	
	/**
	 * processInputFromBoat
	 * Gets the input from the boat and places this in the BoatDataWrapper.
	 * The wrapper will be send to the DashboardController (via MainController).
	 */
	protected synchronized void processInputFromBoat()
	{
		String strReadedLine = btConnection.readLine();
		// Check if any did go wrong, or there was no data
		if(strReadedLine == null)
		{
			return;
		}
		// Turn string into command
		Command cmd = CommandConverter.string2Command(strReadedLine);
		
		// If noCommand.. just ignore!
		if(cmd instanceof NoCommand)
		{
			return;
		}
		// Send command to main controller
		mController.addToBoatDataWrapper(cmd);
		mController.setBluetoothConnectionIsActive(btConnection.isConnected());
	}
	/**
	 * setReady
	 * Sets the flag to true, which causes the run to stop
	 */
	public synchronized void setReady()
	{
		isReady = true;
	}
	
	/**
	 * Get command value and let output class execute the command value.
	 * @param command = the command given by UserInput.
	 */
	protected void processOutputToBoat(Command p_cmdCommand)
	{
		// Send the command to the BT class
		btConnection.processCommand(p_cmdCommand);
		//processCommand(p_cmdCommand);
	}
	public void stop()
	{
		btConnection.close();
	}
	/**
	 * connectBT
	 * Try to connect BT
	 */
	private void connectBT()
	{
		// Check if we are connected
		if(btConnection.isConnected())
			return;
		
		// Try to connect..
		if(btConnection.connect())
		{
			if(Debug.DEBUGGEN)
			{
				Debug.writeMessage("Connecting BT in communication class: Connection OK");
			}
		}
		else 
		{
			if(Debug.DEBUGGEN)
			{
				Debug.writeMessage("Connecting BT in communication class: Connection failed");
			}
		}
	}
	
	/**
	 * doRun
	 * Start a loop for the communication.
	 */
	public void doRun(){
		// Config!
		config();
		// Connect!
		connectBT();
		
		while(!isReady)
		{	
			// Read data from boat
			processInputFromBoat();
			
			// Check if we have something to send to the boat!
			if(!stckCommand.isEmpty())
			{
				// Process info 
				processOutputToBoat(stckCommand.pop());
			}		
		}	
		// Close connection
		btConnection.close();		
	}
	
	public void run(){
		doRun();
	}
}
